package me.yricky.alia.data.shape

import me.yricky.alia.data.base.Coord
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

/**
 * @author Yricky
 * @date 2022/1/27
 */

/**
 * 单个图形的抽象，可直接抽象为点的集合
 */
interface Shape {
    val vertices:List<Coord>

    val bBox: Box get() {
        return if (vertices.isEmpty()) {
            defBox
        } else {
            Box(
                lt = vertices.reduce { c1, c2 -> Coord(min(c1.x, c2.x), min(c1.y, c2.y)) },
                rb = vertices.reduce { c1, c2 -> Coord(max(c1.x, c2.x), max(c1.y, c2.y)) }
            )
        }
    }
}

fun Shape.contains(dot:Coord):Boolean{
    return when(this){
        is Box -> {
            lt.x <= dot.x &&
            lt.y <= dot.y &&
            rb.x > dot.x &&
            rb.y > dot.y
        }
        is Text -> abs(dot.x - coord.x) + abs(dot.y - coord.y) < 8
        is Polygon ->{
            var contain = false
            if(vertices.size > 2){
                val firstV = vertices[0]
                val iterator = vertices.iterator()
                var d1 = iterator.next()
                var d2 = iterator.next()
                while ((d1 !== firstV) || (d2 !== firstV)){
                    if(
                        d1.x <= dot.x &&
                        d2.x <= dot.x &&
                        min(d1.y,d2.y) <= dot.y &&
                        max(d1.y,d2.y) > dot.y
                    ){
                        contain = !contain
                    } else if(
                        min(d1.x,d2.x) <= dot.x &&
                        max(d1.x,d2.x) > dot.x &&
                        min(d1.y,d2.y) <= dot.y &&
                        max(d1.y,d2.y) > dot.y
                    ){
                        val k = (d2.y-d1.y).toFloat()/(d2.x-d1.x)
                        if( (k> 0 && dot.y.toFloat() < (k*(dot.x-d1.x)+d1.y)) ||
                            (k< 0 && dot.y.toFloat() > (k*(dot.x-d1.x)+d1.y))    ){
                            contain = !contain
                        }
                    }
                    d1 = d2
                    d2 = if(iterator.hasNext()) iterator.next() else firstV
                }
            }
            contain
        }
        else -> false
    }
}



